
export function deepCopy(target, map = new WeakMap()) {
    const mapTag = "[object Map]";
    const setTag = "[object Set]";
    const arrayTag = "[object Array]";
    const objectTag = "[object Object]";
    const argsTag = "[object Arguments]";

    const boolTag = "[object Boolean]";
    const dateTag = "[object Date]";
    const numberTag = "[object Number]";
    const stringTag = "[object String]";
    const symbolTag = "[object Symbol]";
    const errorTag = "[object Error]";
    const regexpTag = "[object RegExp]";
    const funcTag = "[object Function]";

    const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag];

    function forEach(array, iteratee) {
        let index = -1;
        const length = array.length;
        while (++index < length) {
            iteratee(array[index], index);
        }
        return array;
    }

    function isObject(target) {
        const type = typeof target;
        return target !== null && (type === "object" || type === "function");
    }

    function getType(target) {
        return Object.prototype.toString.call(target);
    }

    function getInit(target) {
        const Ctor = target.constructor;
        return new Ctor();
    }

    function cloneSymbol(targe) {
        return Object(Symbol.prototype.valueOf.call(targe));
    }

    function cloneReg(targe) {
        const reFlags = /\w*$/;
        const result = new targe.constructor(targe.source, reFlags.exec(targe));
        result.lastIndex = targe.lastIndex;
        return result;
    }

    function cloneOtherType(targe, type) {
        const Ctor = targe.constructor;
        switch (type) {
            case boolTag:
            case numberTag:
            case stringTag:
            case errorTag:
            case dateTag:
                return new Ctor(targe);
            case regexpTag:
                return cloneReg(targe);
            case symbolTag:
                return cloneSymbol(targe);
            default:
                return null;
        }
    }

    // 克隆原始类型
    if (!isObject(target)) {
        return target;
    }

    // 初始化
    const type = getType(target);
    let cloneTarget;
    if (deepTag.includes(type)) {
        cloneTarget = getInit(target, type);
    } else {
        return cloneOtherType(target, type);
    }

    // 防止循环引用
    if (map.get(target)) {
        return map.get(target);
    }
    map.set(target, cloneTarget);

    // 克隆set
    if (type === setTag) {
        target.forEach(value => {
            cloneTarget.add(deepCopy(value, map));
        });
        return cloneTarget;
    }

    // 克隆map
    if (type === mapTag) {
        target.forEach((value, key) => {
            cloneTarget.set(key, deepCopy(value, map));
        });
        return cloneTarget;
    }

    // 克隆对象和数组
    const keys = type === arrayTag ? undefined : Object.keys(target);
    forEach(keys || target, (value, key) => {
        if (keys) {
            key = value;
        }
        cloneTarget[key] = deepCopy(target[key], map);
    });

    return cloneTarget;
}


/**
 * 创建一个随机字符串并返回
 */
 export const createRandomStr = function (length = 8) {
    var aryNum = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
    let str = "";
    let len = aryNum.length;

    for (let i = 0; i < length; i++) {
        let random = Math.floor(Math.random() * len);
        str += aryNum[random];
    }
    return str;
};